package com.abso.sunlight.api;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.dom4j.Element;

/**
 * The information from one Senate Office of Public Records lobbyist disclosure filing.
 */
public class Filing {

    /** Unique id of the filing. */
    private String filingId;

    /** Period of the filing (undetermined, H1, H2, Q1, Q2, Q3, Q4). */
    private String filingPeriod;

    /** Date filing was sent to Senate. */
    private String filingDate;

    /** Total amount of expenditures on filing. */
    private String filingAmount;

    /** Year filing refers to. */
    private String filingYear;

    /** Type of filing (eg. amendment, termination, etc.). */
    private String filingType;

    /** PDF of filing available from SOPR. */
    private String filingPdf;

    /** Unique senate id# assigned to client. */
    private String clientSenateId;

    /** Name of client lobbying is done on behalf of. */
    private String clientName;

    /** Country client is located in. */
    private String clientCountry;

    /** State client is located in (if country is US). */
    private String clientState;

    /** Client's primary place of business. */
    private String clientPPBCountry;

    /** Client's primary place of business (state if client is in US). */
    private String clientPPBState;

    /** Text description of client. */
    private String clientDescription;

    /** First name of contact person at client. */
    private String clientContactFirstName;

    /** Middle name of contact person at client. */
    private String clientContactMiddleName;

    /** Last name of contact person at client. */
    private String clientContactLastName;

    /** Name suffix (Jr., III, etc.) of contact person at client. */
    private String clientContactNameSuffix;

    /** Unique senate id# assigned to registrant (lobbying firm). */
    private String registrantSenateId;

    /** Name of lobbying firm. */
    private String registrantName;

    /** Text description of registrant. */
    private String registrantDescription;

    /** Country registrant is located in. */
    private String registrantCountry;

    /** The filing's issues. */
    private List<FilingIssue> issues;

    /** The involved lobbyists. */
    private List<FilingLobbyist> lobbyists;

    /** Registrant's primary place of business. */
    private String registrantPpbCountry;

    /**
     * Constructs a new filing.
     * 
     * @param elem
     *            the XML holding filing information.
     * @throws SunlightException
     *             if an exception occurred creating the filing.
     */
    public Filing(Element elem) {
        this.filingId = SunlightDataUtils.getString(elem, "filing_id");
        this.filingPeriod = SunlightDataUtils.getString(elem, "filing_period");
        this.filingDate = SunlightDataUtils.getString(elem, "filing_date");
        this.filingAmount = SunlightDataUtils.getString(elem, "filing_amount");
        this.filingYear = SunlightDataUtils.getString(elem, "filing_year");
        this.filingType = SunlightDataUtils.getString(elem, "filing_type");
        this.filingPdf = SunlightDataUtils.getString(elem, "filing_pdf");
        this.clientSenateId = SunlightDataUtils.getString(elem, "client_senate_id");
        this.clientName = SunlightDataUtils.getString(elem, "client_name");
        this.clientCountry = SunlightDataUtils.getString(elem, "client_country");
        this.clientState = SunlightDataUtils.getString(elem, "client_state");
        this.clientPPBCountry = SunlightDataUtils.getString(elem, "client_ppb_country");
        this.clientPPBState = SunlightDataUtils.getString(elem, "client_ppb_state");
        this.clientDescription = SunlightDataUtils.getString(elem, "client_description");
        this.clientContactFirstName = SunlightDataUtils.getString(elem, "client_contact_firstname");
        this.clientContactMiddleName = SunlightDataUtils.getString(elem, "client_contact_middlename");
        this.clientContactLastName = SunlightDataUtils.getString(elem, "client_contact_lastname");
        this.clientContactNameSuffix = SunlightDataUtils.getString(elem, "client_contact_suffix");
        this.registrantSenateId = SunlightDataUtils.getString(elem, "registrant_senate_id");
        this.registrantName = SunlightDataUtils.getString(elem, "registrant_name");
        this.registrantDescription = SunlightDataUtils.getString(elem, "registrant_description");
        this.registrantCountry = SunlightDataUtils.getString(elem, "registrant_country");
        this.registrantPpbCountry = SunlightDataUtils.getString(elem, "registrant_ppb_country");
        this.issues = new ArrayList<FilingIssue>();
        for (Iterator<?> i = elem.selectNodes("issues/issue").iterator(); i.hasNext();) {
            Element subElem = (Element) i.next();
            issues.add(new FilingIssue(subElem));
        }
        this.issues = Collections.unmodifiableList(issues);
        this.lobbyists = new ArrayList<FilingLobbyist>();
        for (Iterator<?> i = elem.selectNodes("lobbyists/lobbyist").iterator(); i.hasNext();) {
            Element subElem = (Element) i.next();
            lobbyists.add(new FilingLobbyist(subElem));
        }
        this.lobbyists = Collections.unmodifiableList(lobbyists);
    }

    /**
     * Returns unique id of the filing.
     * 
     * @return unique id of the filing.
     */
    public String getFilingId() {
        return filingId;
    }

    /**
     * Returns period of the filing (undetermined, H1, H2, Q1, Q2, Q3, Q4).
     * 
     * @return period of the filing (undetermined, H1, H2, Q1, Q2, Q3, Q4).
     */
    public String getFilingPeriod() {
        return filingPeriod;
    }

    /**
     * Returns date filing was sent to Senate.
     * 
     * @return date filing was sent to Senate.
     */
    public String getFilingDate() {
        return filingDate;
    }

    /**
     * Returns total amount of expenditures on filing.
     * 
     * @return total amount of expenditures on filing.
     */
    public String getFilingAmount() {
        return filingAmount;
    }

    /**
     * Returns year filing refers to.
     * 
     * @return year filing refers to.
     */
    public String getFilingYear() {
        return filingYear;
    }

    /**
     * Returns type of filing (eg. amendment, termination, etc.).
     * 
     * @return type of filing (eg. amendment, termination, etc.).
     */
    public String getFilingType() {
        return filingType;
    }

    /**
     * Returns pDF of filing available from SOPR.
     * 
     * @return pDF of filing available from SOPR.
     */
    public String getFilingPdf() {
        return filingPdf;
    }

    /**
     * Returns unique senate id# assigned to client.
     * 
     * @return unique senate id# assigned to client.
     */
    public String getClientSenateId() {
        return clientSenateId;
    }

    /**
     * Returns name of client lobbying is done on behalf of.
     * 
     * @return name of client lobbying is done on behalf of.
     */
    public String getClientName() {
        return clientName;
    }

    /**
     * Returns country client is located in.
     * 
     * @return country client is located in.
     */
    public String getClientCountry() {
        return clientCountry;
    }

    /**
     * Returns state client is located in (if country is US).
     * 
     * @return state client is located in (if country is US).
     */
    public String getClientState() {
        return clientState;
    }

    /**
     * Returns client's primary place of business.
     * 
     * @return client's primary place of business.
     */
    public String getClientPPBCountry() {
        return clientPPBCountry;
    }

    /**
     * Returns client's primary place of business (state if client is in US).
     * 
     * @return client's primary place of business (state if client is in US).
     */
    public String getClientPPBState() {
        return clientPPBState;
    }

    /**
     * Returns text description of client.
     * 
     * @return text description of client.
     */
    public String getClientDescription() {
        return clientDescription;
    }

    /**
     * Returns first name of contact person at client.
     * 
     * @return first name of contact person at client.
     */
    public String getClientContactFirstName() {
        return clientContactFirstName;
    }

    /**
     * Returns middle name of contact person at client.
     * 
     * @return middle name of contact person at client.
     */
    public String getClientContactMiddleName() {
        return clientContactMiddleName;
    }

    /**
     * Returns last name of contact person at client.
     * 
     * @return last name of contact person at client.
     */
    public String getClientContactLastName() {
        return clientContactLastName;
    }

    /**
     * Returns name suffix (Jr., III, etc.) of contact person at client.
     * 
     * @return name suffix (Jr., III, etc.) of contact person at client.
     */
    public String getClientContactNameSuffix() {
        return clientContactNameSuffix;
    }

    /**
     * Returns unique senate id# assigned to registrant (lobbying firm).
     * 
     * @return unique senate id# assigned to registrant (lobbying firm).
     */
    public String getRegistrantSenateId() {
        return registrantSenateId;
    }

    /**
     * Returns name of lobbying firm.
     * 
     * @return name of lobbying firm.
     */
    public String getRegistrantName() {
        return registrantName;
    }

    /**
     * Returns text description of registrant.
     * 
     * @return text description of registrant.
     */
    public String getRegistrantDescription() {
        return registrantDescription;
    }

    /**
     * Returns country registrant is located in.
     * 
     * @return country registrant is located in.
     */
    public String getRegistrantCountry() {
        return registrantCountry;
    }

    /**
     * Returns registrant's primary place of business.
     * 
     * @return registrant's primary place of business.
     */
    public String getRegistrantPpbCountry() {
        return registrantPpbCountry;
    }

    /**
     * Returns the (unmodifiable) list of issues.
     * 
     * @return the list of issues.
     */
    public List<FilingIssue> getIssueList() {
        return issues;
    }

    /**
     * Returns the (unmodifiable) list of involved lobbyists.
     * 
     * @return the list of lobbyists.
     */
    public List<FilingLobbyist> getLobbyistList() {
        return lobbyists;
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
    }

    @Override
    public int hashCode() {
        return getFilingId().hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Filing)) {
            return false;
        }
        return getFilingId().equals(((Filing) obj).getFilingId());
    }
}
